package org.irri.smta.service.impl;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.inject.Inject;
import javax.inject.Named;

import org.apache.commons.lang.StringUtils;
import org.irri.smta.common.Constants;
import org.irri.smta.domain.Material;
import org.irri.smta.domain.SmtaReport;
import org.irri.smta.repository.ISmtaReportRepository;
import org.irri.smta.service.ISmtaGenerateService;
import org.irri.smta.ui.bean.ResourceConfigBean;
import org.irri.smta.util.ConverterUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.annotation.Transactional;

@Named("smtaGenerateService")
@Transactional(readOnly = true)
public class SmtaGenerateService implements ISmtaGenerateService<SmtaReport, Long>{
	
	private static final Logger LOGGER = LoggerFactory
			.getLogger(SmtaGenerateService.class);

	@Inject
	@Named("resourceConfigBean")
	private ResourceConfigBean resourceConfigBean;

	@Inject
	@Named("smtaReportRepository")
	private ISmtaReportRepository smtaReportRepository;

	@Override
	public SmtaReport create(SmtaReport smtaReport) {
		throw new UnsupportedOperationException("Create is unsupported!");
	}

	@Override
	public SmtaReport update(SmtaReport smtaReport) throws Exception {
		throw new UnsupportedOperationException("Update is unsupported!");
	}

	@Override
	public SmtaReport delete(Long id) throws Exception {
		throw new UnsupportedOperationException("Delete is unsupported!");
	}

	@Override
	public List<SmtaReport> findAll() {
		throw new UnsupportedOperationException("findAll is unsupported!");
	}

	@Override
	public SmtaReport findById(Long id) {
		LOGGER.debug("SmtaReport findById(Long id): " + id);
		return smtaReportRepository.findOne(id);
	}
	
	public SmtaReport findBySymbol(String symbol) {
		LOGGER.debug("SmtaReport findBySymbol(String symbol): " + symbol);
		List<SmtaReport> list = smtaReportRepository.findBySymbol(symbol);
		if (!list.isEmpty()) {
			return list.get(0);
		}
		return null;
	}

	@Override
	public void generatePdf(Map<String, String> paramMap, String mtaType) throws Exception {
		LOGGER.info("generateSmtaPdf(Map<String, String> paramMap)");
		String templateDirectory = "";
		String templateFilename = "";
		String generatedDirectory = "";
		String generatedFilename = "";
		if (mtaType.equals(Constants.MTA_TYPE_0)) {
			templateDirectory = paramMap.get(Constants.KEY_SMTA_TEMPLATE_DIRECTORY);
			templateFilename = paramMap.get(Constants.KEY_SMTA_TEMPLATE_FILENAME);
			generatedDirectory = paramMap.get(Constants.KEY_SMTA_GENERATED_DIRECTORY);
			generatedFilename = paramMap.get(Constants.KEY_SMTA_GENERATED_FILENAME);
		} else {
			templateDirectory = paramMap.get(Constants.KEY_MTA_TEMPLATE_DIRECTORY);
			templateFilename = paramMap.get(Constants.KEY_MTA_TEMPLATE_FILENAME);
			generatedDirectory = paramMap.get(Constants.KEY_MTA_GENERATED_DIRECTORY);
			generatedFilename = paramMap.get(Constants.KEY_MTA_GENERATED_FILENAME);
		}
		
		File templateFile = new File(templateDirectory + "/" + templateFilename);
		
		String smtaId = paramMap.get(Constants.KEY_IRRI_SMTA_ID);
		String shuRequestId = paramMap.get(Constants.KEY_SHU_REQUEST_ID);
		String smtaWebsiteUrl = paramMap.get(Constants.KEY_SMTA_WEBSITE_URL);
		
		SmtaReport smtaReport = findBySymbol(smtaId);
		if (smtaReport != null) {
			String templateContents = ConverterUtils.getContents(templateFile);
			
			Map<String, String> substitutionData = new HashMap<String, String>();
			// Substitute SMTA ID for bookmark BOOKMARK_START_SMTAID
			substitutionData.put(Constants.BOOKMARK_START_SMTAID, Constants.BOOKMARK_START_SMTAID + smtaId);
			// Substitute SHU ID for bookmark BOOKMARK_START_SHUID
			substitutionData.put(Constants.BOOKMARK_START_SHUID, Constants.BOOKMARK_START_SHUID + shuRequestId);
			// Substitute SMTA ID for bookmark BOOKMARK_START_SHUIDFOOTER
			substitutionData.put(Constants.BOOKMARK_START_SMTAIDFOOTER, Constants.BOOKMARK_START_SMTAIDFOOTER + smtaId);
			// Substitute SHU ID for bookmark BOOKMARK_START_SHUIDFOOTER
			substitutionData.put(Constants.BOOKMARK_START_SHUIDFOOTER, Constants.BOOKMARK_START_SHUIDFOOTER + shuRequestId);
			// Substitute SMTA ID for bookmark BOOKMARK_START_SMTAIDFOOTERP1
			substitutionData.put(Constants.BOOKMARK_START_SMTAIDFOOTERP1, Constants.BOOKMARK_START_SMTAIDFOOTERP1 + smtaId);
			// Substitute SHU ID for bookmark BOOKMARK_START_SHUIDFOOTERP1
			substitutionData.put(Constants.BOOKMARK_START_SHUIDFOOTERP1, Constants.BOOKMARK_START_SHUIDFOOTERP1 + shuRequestId);
			// Substitute web site URL
			substitutionData.put(Constants.BOOKMARK_START_URL, Constants.BOOKMARK_START_URL + smtaWebsiteUrl);

			// If agreement = 'SW', then delete section between bookmark BOOKMARK_START_ART10SI and BOOKMARK_END_ART10SI
			if (Constants.SMTA_TYPE_SHRINK_WRAPPED.equalsIgnoreCase(smtaReport.getSmtaType())) {
				int beginIndex = templateContents.indexOf(Constants.BOOKMARK_START_ART10SI);
				if (beginIndex >= 0) {
					int endIndex = templateContents.indexOf(Constants.BOOKMARK_END_ART10SI);
					if (endIndex >= 0) {
						endIndex += Constants.BOOKMARK_END_ART10SI.length();
					}
					if (endIndex > beginIndex) {
						String substr = templateContents.substring(beginIndex, endIndex);
						// Essentially, remove the text between BOOKMARK_START_ART10SI and BOOKMARK_END_ART10SI
						substitutionData.put(substr, "");
					}
				}
			}
			// If agreement = 'SI', then substitute BOOKMARK_START_PROVIDERSI 
			// and delete section between bookmark BOOKMARK_START_ART10SW and BOOKMARK_END_ART10SW
			else if (Constants.SMTA_TYPE_SIGNED.equalsIgnoreCase(smtaReport.getSmtaType())) {
				String irriProvAoDetails = ", " + smtaReport.getProvAoName() + ", " + smtaReport.getProvAoTitle() + ", " + smtaReport.getProvAoEmail() + ", " + smtaReport.getProvAoPhone() + ", " + smtaReport.getProvAoFax();
				substitutionData.put(Constants.BOOKMARK_START_PROVIDERSI, Constants.BOOKMARK_START_PROVIDERSI + irriProvAoDetails);
				
				String contents = ConverterUtils.getContents(templateFile);
				int beginIndex = contents.indexOf(Constants.BOOKMARK_START_ART10SW);
				if (beginIndex >= 0) {
					int endIndex = contents.indexOf(Constants.BOOKMARK_END_ART10SW);
					if (endIndex >= 0) {
						endIndex += Constants.BOOKMARK_END_ART10SW.length();
					}
					if (endIndex > beginIndex) {
						String substr = contents.substring(beginIndex, endIndex);
						// Essentially, remove the text between BOOKMARK_START_ART10SW and BOOKMARK_END_ART10SW
						substitutionData.put(substr, "");
					}
				}

				substitutionData.put(Constants.BOOKMARK_START_PROV_AO, Constants.BOOKMARK_START_PROV_AO + smtaReport.getProvAoName() + ", " + smtaReport.getProvAoTitle());

				substitutionData.put(Constants.BOOKMARK_START_PROV_AO_NAME, Constants.BOOKMARK_START_PROV_AO_NAME + smtaReport.getProvAoName());
				
				substitutionData.put(Constants.BOOKMARK_START_PROV_AO_TITLE, Constants.BOOKMARK_START_PROV_AO_TITLE + smtaReport.getProvAoTitle());

				substitutionData.put(Constants.BOOKMARK_START_SENDER_NAME, Constants.BOOKMARK_START_SENDER_NAME + smtaReport.getSenderName());

				substitutionData.put(Constants.BOOKMARK_START_SENDER_TITLE, Constants.BOOKMARK_START_SENDER_TITLE + smtaReport.getSenderTitle());

				substitutionData.put(Constants.BOOKMARK_START_RECIP_AO_NAME, Constants.BOOKMARK_START_RECIP_AO_NAME + smtaReport.getRecipAoName());
				
				substitutionData.put(Constants.BOOKMARK_START_RECIP_AO_TITLE, Constants.BOOKMARK_START_RECIP_AO_TITLE + smtaReport.getRecipAoTitle());

				substitutionData.put(Constants.BOOKMARK_START_RECIPSCI_NAME, Constants.BOOKMARK_START_RECIPSCI_NAME + smtaReport.getRecipSciName());
				
				substitutionData.put(Constants.BOOKMARK_START_RECIPSCI_TITLE, Constants.BOOKMARK_START_RECIPSCI_TITLE + smtaReport.getRecipSciTitle());
			}

			// If recipient type = 'in' then substitute recipient individual details
			if (Constants.RECIPIENT_TYPE_INDIVIDUAL.equalsIgnoreCase(smtaReport.getRecipientType())) {
				String recipientDetails = smtaReport.getRecipientName() + ", " + smtaReport.getRecipientAddress() + ", " + smtaReport.getRecipientCountry();
				substitutionData.put(Constants.BOOKMARK_START_RECIPIENT, Constants.BOOKMARK_START_RECIPIENT + recipientDetails);
			}
			// If recipient type = 'or' and agreement = 'SW' then substitute recipient organization details
			else if (Constants.SMTA_TYPE_SHRINK_WRAPPED.equalsIgnoreCase(smtaReport.getSmtaType()) 
					&& Constants.RECIPIENT_TYPE_ORGANIZATION.equalsIgnoreCase(smtaReport.getRecipientType())) {
				String recipientDetails = smtaReport.getRecipientOrganizationName() + ", " + smtaReport.getRecipientAddress() + ", " + smtaReport.getRecipientCountry();
				substitutionData.put(Constants.BOOKMARK_START_RECIPIENT, Constants.BOOKMARK_START_RECIPIENT + recipientDetails);
			} 
			// If recipient type = 'or' and agreement = 'SI' then substitute recipient organization details
			else if (Constants.RECIPIENT_TYPE_ORGANIZATION.equalsIgnoreCase(smtaReport.getRecipientType())
					&& Constants.SMTA_TYPE_SIGNED.equalsIgnoreCase(smtaReport.getSmtaType())) {
				// If SMTA then use Recipient organization name, Recipient Address, Recipient Country, ", represented by " & Recip_AO_name, Recip_AO_title, RecipAO_email, Recip_AO_phone, Recip_AO_fax
				if (mtaType.equals(Constants.MTA_TYPE_0)) {
					String recipientOrganizationDetails = smtaReport.getRecipientOrganizationName() + ", " + smtaReport.getRecipientAddress() + ", " + smtaReport.getRecipientCountry();
					String recipientAuthorizedOfficialDetails = smtaReport.getRecipAoName() + ", " + smtaReport.getRecipAoTitle() + ", " + smtaReport.getRecipAoEmail() + ", " + smtaReport.getRecipAoPhone() + ", " + smtaReport.getRecipAoFax();
					String recipientDetails = recipientOrganizationDetails + ", represented by " + recipientAuthorizedOfficialDetails;
					substitutionData.put(Constants.BOOKMARK_START_RECIPIENT, Constants.BOOKMARK_START_RECIPIENT + recipientDetails);
					
					substitutionData.put(Constants.BOOKMARK_START_ART10RECIPIENT, Constants.BOOKMARK_START_ART10RECIPIENT + smtaReport.getRecipientOrganizationName());
				}
				// If not SMTA then use Recipient organization name, Recipient Address, Recipient Country
				else {
					String recipientDetails = smtaReport.getRecipientOrganizationName() + ", " + smtaReport.getRecipientAddress() + ", " + smtaReport.getRecipientCountry();
					substitutionData.put(Constants.BOOKMARK_START_RECIPIENT, Constants.BOOKMARK_START_RECIPIENT + recipientDetails);
				}
				
				String authorizedDetails = "";
				if (mtaType.equals(Constants.MTA_TYPE_0)) {
					authorizedDetails = smtaReport.getRecipAoName() + ", " + smtaReport.getRecipAoTitle();
				} else {
					authorizedDetails = smtaReport.getRecipAoName();
				}
				substitutionData.put(Constants.BOOKMARK_START_ART10AUTHORIZED, Constants.BOOKMARK_START_ART10AUTHORIZED + authorizedDetails);
				
			}
			// If recipient type = 'in' and agreement = 'SI' then substitute recipient individual details
			else if (Constants.RECIPIENT_TYPE_INDIVIDUAL.equalsIgnoreCase(smtaReport.getRecipientType())
					&& Constants.SMTA_TYPE_SIGNED.equalsIgnoreCase(smtaReport.getSmtaType())) {
				substitutionData.put(Constants.BOOKMARK_START_ART10AUTHORIZED, Constants.BOOKMARK_START_ART10AUTHORIZED + smtaReport.getRecipientName());
				
				substitutionData.put(Constants.BOOKMARK_START_ART10RECIPIENT, Constants.BOOKMARK_START_ART10RECIPIENT + smtaReport.getRecipientName());
			}
			
			if (!mtaType.equalsIgnoreCase(Constants.MTA_TYPE_0)) {
				substitutionData.put(Constants.BOOKMARK_START_RECIP_AO_NAME, Constants.BOOKMARK_START_RECIP_AO_NAME + smtaReport.getRecipAoName());
				substitutionData.put(Constants.BOOKMARK_START_RECIP_AO_TITLE, Constants.BOOKMARK_START_RECIP_AO_TITLE + smtaReport.getRecipAoTitle());
				substitutionData.put(Constants.BOOKMARK_START_RECIPSCI_NAME, Constants.BOOKMARK_START_RECIPSCI_NAME + smtaReport.getRecipSciName());
				substitutionData.put(Constants.BOOKMARK_START_RECIPSCI_TITLE, Constants.BOOKMARK_START_RECIPSCI_TITLE + smtaReport.getRecipSciTitle());
			}
			
			// Substitute date today
			Date now = new Date();
			SimpleDateFormat format = new SimpleDateFormat("d MMM yyyy");
			String dateToday = format.format(now);
			substitutionData.put(Constants.BOOKMARK_START_DATE, Constants.BOOKMARK_START_DATE + dateToday);
			
			Set<Material> underDevSet = new HashSet<Material>();
			Set<Material> notUnderDevSet = new HashSet<Material>();
			Set<Material> ancestorSet = new HashSet<Material>();
			
			LOGGER.info("Retrieving material list");
			List<Material> materialList = smtaReport.getMaterials();
			Iterator<Material> iter = materialList.iterator();
			while (iter.hasNext()) {
				Material material = iter.next();
				if (StringUtils.isNotEmpty(material.getSampleId())) {
					if (("y").equalsIgnoreCase(material.getPud())) {
						underDevSet.add(material);
					} else if (("n").equalsIgnoreCase(material.getPud())) {
						notUnderDevSet.add(material);
					}
				}
				if (StringUtils.isNotEmpty(material.getAncestry())) {
					if (ancestorSet.add(material));
				}
			}
			
			iter = notUnderDevSet.iterator();
			if (mtaType.equals(Constants.MTA_TYPE_0) && !iter.hasNext()) {
				LOGGER.info("There are no materials not under development. Removing " + Constants.BOOKMARK_START_NPUDSECTION + " ... " + Constants.BOOKMARK_END_NPUDSECTION);
				int beginIndex = templateContents.indexOf(Constants.BOOKMARK_START_NPUDSECTION);
				if (beginIndex >= 0) {
					int endIndex = templateContents.indexOf(Constants.BOOKMARK_END_NPUDSECTION);
					if (endIndex >= 0) {
						endIndex += Constants.BOOKMARK_END_NPUDSECTION.length();
					}
					if (endIndex > beginIndex) {
						String substr = templateContents.substring(beginIndex, endIndex);
						substitutionData.put(substr, "");
					}
				}
			} else {
				Set<String> items = new HashSet<String>();
				while (iter.hasNext()) {
					Material material = iter.next();
					items.add(material.getSampleId().replaceAll("\\r\\n|\\r|\\n", " ").trim());
				}
				
				StringBuffer sb = new StringBuffer();
				Iterator<String> strIter = items.iterator();
				while (strIter.hasNext()) {
					String item = strIter.next();
					sb.append(item);
					sb.append(Constants.RTF_PARAGRAPH);
					sb.append(" ");
				}
				substitutionData.put(Constants.BOOKMARK_START_NPUD, Constants.BOOKMARK_START_NPUD + sb.toString());
			}
			
			iter = underDevSet.iterator();
			if (mtaType.equals(Constants.MTA_TYPE_0) && !iter.hasNext()) {
				LOGGER.info("There are no materials under development. Removing " + Constants.BOOKMARK_START_PUDSECTION + " ... " + Constants.BOOKMARK_END_PUDSECTION);
				int beginIndex = templateContents.indexOf(Constants.BOOKMARK_START_PUDSECTION);
				if (beginIndex >= 0) {
					int endIndex = templateContents.indexOf(Constants.BOOKMARK_END_PUDSECTION);
					if (endIndex >= 0) {
						endIndex += Constants.BOOKMARK_END_PUDSECTION.length();
					}
					if (endIndex > beginIndex) {
						String substr = templateContents.substring(beginIndex, endIndex);
						substitutionData.put(substr, "");
					}
				}
			} else {
				Set<String> items = new HashSet<String>();
				while (iter.hasNext()) {
					Material material = iter.next();
					items.add(material.getSampleId().replaceAll("\\r\\n|\\r|\\n", " ").trim());
				}
				
				StringBuffer sb = new StringBuffer();
				Iterator<String> strIter = items.iterator();
				while (strIter.hasNext()) {
					String item = strIter.next();
					sb.append(item);
					sb.append(Constants.RTF_PARAGRAPH);
					sb.append(" ");
				}
				substitutionData.put(Constants.BOOKMARK_START_PUD, Constants.BOOKMARK_START_PUD + sb.toString());
			}
			
			Set<String> items = new HashSet<String>();
			iter = ancestorSet.iterator();
			while (iter.hasNext()) {
				Material material = iter.next();
				items.add(material.getAncestry().replaceAll("\\r\\n|\\r|\\n", " ").trim());
			}

			StringBuffer sb = new StringBuffer();
			Iterator<String> strIter = items.iterator();
			while (strIter.hasNext()) {
				String item = strIter.next();
				sb.append(item);
				sb.append(Constants.RTF_PARAGRAPH);
				sb.append(" ");
			}
			substitutionData.put(Constants.BOOKMARK_START_MLSANCESTORS, Constants.BOOKMARK_START_MLSANCESTORS + sb.toString());

			String intermediateDocumentFilepath = ConverterUtils.generateRtf(substitutionData, templateDirectory, templateFilename, generatedDirectory);
			LOGGER.info("Convert document to PDF");
			LOGGER.info("OpenOffice directory: " + resourceConfigBean.getOpenOfficeDirectory());
			LOGGER.info("Intermediate document filepath: " + intermediateDocumentFilepath);
			LOGGER.info("Generated directory: " + generatedDirectory);
			LOGGER.info("Generated document file: " + generatedFilename);
			ConverterUtils.delete(new File(generatedDirectory + "/" + generatedFilename));
			ConverterUtils.convert(resourceConfigBean.getOpenOfficeDirectory(), intermediateDocumentFilepath, generatedDirectory, generatedFilename);
			ConverterUtils.delete(new File(intermediateDocumentFilepath));
		} else {
			LOGGER.info("SMTA report for symbol " + smtaId + " not found.");
		}
	}

}
